/* boris*/
#include "libBigNum.h"


//Unary  operator +//
big_number big_number:: operator +()
 {
	 big_number temp;
	 temp._sign=(temp._sign==true);
     return temp;
 }

big_number big_number::operator +(const big_number &param) const
{
  big_number temp;
  if(this->_sign==param._sign)      
  {
      temp=ADD(*this,param);
	  temp._sign=_sign;
	  return temp;
	   
  }//end if
  
  else
  {
	if (ABS(*this)>ABS(param))			
		{
			temp._sign=_sign; 
			return temp.SUB(*this,param);			
		} //end if
	else 
		{
			temp._sign=param._sign; 
			return temp.SUB(param,*this);			
		}//end else
  }//end else
}

big_number big_number::ADD(const big_number &x, const big_number &y) const
{
	big_number temp;
	unsigned long *help_arr, *help_arr1;
	int carry=0;
	int i;
	int n_int1, n_int2;
	unsigned short tikun_index_x,tikun_index_y ,  temp_int_p,  temp_frac_p ;      //integer part of number, integer part of number
	if(x._fractionalPart>y._fractionalPart)                                       // max_fraction_part_of {x,y}<-size of fraction part of number
		temp._fractionalPart=x._fractionalPart; 
	else 
		temp._fractionalPart=y._fractionalPart;
	if(x._arr_size-x._fractionalPart >y._arr_size-y._fractionalPart)			 // max_integer_part_of_ {x,y}<-integer part of number
		temp_int_p=x._arr_size-x._fractionalPart;
	else 
		temp_int_p=y._arr_size-y._fractionalPart;

	temp._arr_size=temp_int_p+temp._fractionalPart;
	   
	tikun_index_x=(temp._arr_size-temp._fractionalPart)-(x._arr_size-x._fractionalPart);//upgrade index for y.num_arr: temp's size integer - y's size integer
    tikun_index_y=(temp._arr_size-temp._fractionalPart)-(y._arr_size-y._fractionalPart);//upgrade index for y.num_arr: temp's size integer - y's size integer
	
	temp._arr_size = temp_int_p + temp._fractionalPart;
	help_arr=(unsigned long*) malloc( temp._arr_size*sizeof(unsigned long));//array allocation for storage result number
	if ( help_arr == NULL)
		throw exception(); //TODO def execption can't allocate memory

	temp_frac_p=temp._fractionalPart;
	n_int1=x._arr_size-x._fractionalPart;
	n_int2=y._arr_size-y._fractionalPart;

	for(i=temp._arr_size-1;i>=temp_int_p;i--)  //calculation of the fractional part for result number
	{
		if(x._fractionalPart>=temp_frac_p && y._fractionalPart>= temp_frac_p)                  //operation for array cells with meaning of both summands
			help_arr[i]=x._num_array[i-tikun_index_x]+y._num_array[i-tikun_index_y]+carry;
		else if (x._fractionalPart>=temp_frac_p)                                               // operation for only array cell with meaning of summand x
		  	help_arr[i]=x._num_array[i-tikun_index_x]+carry;
		else																				   // operation for only  array cell with meaning of summand y
			help_arr[i]=y._num_array[i-tikun_index_y]+carry;
		carry=help_arr[i]/(1000000000);
		help_arr[i]=help_arr[i]%(1000000000);
		temp_frac_p--;
	}// end for
	for(i=temp_int_p-1; i>=0;i--)																//calculation of the integer part for result number
	{
		if( n_int1>0 && n_int2>0)																//operation for array cells with meaning of both summands
			help_arr[i]=x._num_array[i-tikun_index_x]+y._num_array[i-tikun_index_y]+carry;
		else if (n_int1>0)																		// operation for only array cell with meaning of summand x
			help_arr[i]=x._num_array[i-tikun_index_x]+carry;
		else                                                                                    // operation for only  array cell with meaning of summand y
		   	help_arr[i]=y._num_array[i-tikun_index_y]+carry;
		carry=help_arr[i]/(1000000000);
		help_arr[i]=help_arr[i]%(1000000000);
		n_int1--;
		n_int2--;
	}//end for

	if(carry)																				    // if there is needing to expand array result
	{
		temp._arr_size++;
		help_arr1= (unsigned long*) malloc( temp._arr_size*sizeof(unsigned long));
		help_arr1[0]=1;
		for(i=1;i<temp._arr_size;i++)                
			help_arr1[i]=help_arr[i-1];

		free(temp._num_array);
		temp._num_array = (unsigned long*) malloc( temp._arr_size*sizeof(unsigned long));
		if ( temp._num_array == NULL)
			throw exception(); //TODO def execption can't allocate memory		
		memcpy(temp._num_array, help_arr1, temp._arr_size*sizeof(unsigned long));
		free(help_arr1);
		free(help_arr);
		return temp;
	}//end if(carry)
			
	free(temp._num_array);
	temp._num_array = (unsigned long*) malloc( temp._arr_size*sizeof(unsigned long));

	if ( temp._num_array == NULL)
		throw exception(); //TODO def execption can't allocate memory

	memcpy(temp._num_array, help_arr, temp._arr_size*sizeof(unsigned long));
	free(help_arr);

	return temp;
}
